#include <stdio.h> 
#include <stdlib.h>
#include <linux/rtc.h> 
#include <sys/ioctl.h> 
#include <sys/time.h> 
#include <sys/types.h> 
#include <fcntl.h> 
#include <unistd.h> 
#include <errno.h> 

int main(void) 
{ 
    int i, fd, retval, irqcount = 0; 
    unsigned long tmp, data; 

    fd = open ("/dev/rtc", O_RDONLY); 
    if (fd ==  -1) { 
        perror("/dev/rtc"); 
        exit(errno); 
    } 
    fprintf(stderr, "\n\tRTC Driver Test Example.\n"); 

    /* Turn on update interrupts (one per second) */ 
    retval = ioctl(fd, RTC_UIE_ON, 0); 
    if (retval == -1) { 
        perror("ioctl"); 
        exit(errno); 
    } 
    fprintf(stderr, "Counting 5 update (1/sec) interrupts from reading /dev/rtc:"); 

    for (i = 1; i < 6; i++) { 
        /* This read will block */ 
        retval = read(fd, &data, sizeof(unsigned long)); 
        if (retval == -1) { 
            perror("read"); 
            exit(errno); 
        } 
        fprintf(stderr, " %d", i); 
        irqcount++; 
    } 

    /* Turn off update interrupts */ 
    retval = ioctl(fd, RTC_UIE_OFF, 0); 
    if (retval == -1) { 
        perror("ioctl"); 
        exit(errno); 
    } 

    /* Read periodic IRQ rate */ 
    retval = ioctl(fd, RTC_IRQP_READ, &tmp); 
    if (retval == -1) { 
        perror("ioctl"); 
        exit(errno); 
    } 
    fprintf(stderr, "\nPeriodic IRQ rate was %ldHz.\n", tmp); 
    fprintf(stderr, "Counting 20 interrupts at:"); 

    /* The frequencies 128Hz, 256Hz, ... 8192Hz are only allowed for root. */ 
    for (tmp = 2; tmp <= 64; tmp *= 2) { 
        retval = ioctl(fd, RTC_IRQP_SET, tmp); 
        if (retval == -1) { 
            perror("ioctl"); 
            exit(errno); 
        } 
        fprintf(stderr, "\n%ldHz:\t", tmp); 

        /* Enable periodic interrupts */ 
        retval = ioctl(fd, RTC_PIE_ON, 0); 
        if (retval == -1) { 
            perror("ioctl"); 
            exit(errno); 
        } 
        for (i = 1; i < 21; i++) { 
            /* This blocks */ 
            retval = read(fd, &data, sizeof(unsigned long)); 
            if (retval == -1) { 
                perror("read"); 
                exit(errno); 
            } 
            fprintf(stderr, " %d",i); 
            irqcount++; 
        } 
        /* Disable periodic interrupts */ 
        retval = ioctl(fd, RTC_PIE_OFF, 0); 
        if (retval == -1) { 
            perror("ioctl"); 
            exit(errno); 
        } 
    } 
    fprintf(stderr, "\n\t *** Test complete ***\n"); 
    fprintf(stderr, "\nTyping \"cat /proc/interrupts\" will show %d more events on IRQ 8.\n", irqcount); 

    close(fd); 

    return 0; 
}
